/*
 * srm 211 div prob 2
 */

import java.util.*;
import java.util.regex.*;
import java.text.*;
import java.math.*;


public class grafixMask
{
    public int[] sortedAreas(String[] rectangles)
    {
	boolean[][] matrix = new boolean[400][600];
	
	for (String rec:rectangles) {
	    String[] recs = rec.split (" ");
	    int[] dims= new int[4];
	    for (int i = 0; i < 4; ++i)
		dims[i] = Integer.parseInt (recs[i]);
	    for (int x = dims[0]; x <= dims[2]; ++x)
		for (int y = dims[1]; y <= dims[3]; ++y)
		    matrix[x][y] = true;
	}
	
	ArrayList<Integer> al = new ArrayList<Integer> ();
	
	for (int i = 0; i < 400; ++i)
	    for (int j = 0; j < 600; ++j) {
		if (matrix[i][j])
		    continue;
		LinkedList<Integer> queue1 = new LinkedList<Integer> (), queue2 = new LinkedList<Integer> ();
		queue1.add (i);
		queue2.add (j);
		HashSet<Integer> visited = new HashSet<Integer> ();
		visited.add (i*600+j);
		while (!queue1.isEmpty ()) {
		    int x = queue1.removeFirst (), y = queue2.removeFirst ();
		    if (x > 0 && !matrix[x-1][y] && !visited.contains (600*(x-1)+y)) {
			queue1.add (x-1);
			queue2.add (y);
			visited.add (600 * (x-1) + y);
		    }
		    if (y > 0 && !matrix[x][y-1] && !visited.contains (600*x+y-1)) {
			queue1.add (x);
			queue2.add (y-1);
			visited.add (600 * x + y - 1);
		    }
		    if (x < 399 && !matrix[x+1][y] && !visited.contains (600*(x+1)+y)) {
			queue1.add (x+1);
			queue2.add (y);
			visited.add (600 * (x+1) + y);
		    }
		    if (y < 599 && !matrix[x][y+1] && !visited.contains (600*x+y+1)) {
			queue1.add (x);
			queue2.add (y+1);
			visited.add (600 * x + y + 1);
		    }
		}
		al.add (visited.size ());
		for (int v:visited) {
		    int x = v/600, y = v%600;
		    matrix[x][y] = true;
		}
	    }
	
	
	Collections.sort (al);
	int[] data = new int[al.size ()];
	for (int i = 0; i < data.length; ++i)
	    data[i] = al.get (i);
	return data;
    }
    

}
//Powered by KawigiEdit 2.1.4 (beta) modified by pivanof!